perm filename DECLAR.MSS[WHT,LSP] blob sn#754056 filedate 1984-05-12 generic text, type T, neo UTF8
@Part[Declar, Root = "CLM.MSS"]
@Comment{Chapter of Common Lisp Manual.  Copyright 1984 Guy L. Steele Jr.⎇


@MyChapter[Declarations]
@label[DECLAR]
@Index[declarations]

Declarations allow you to specify extra information about your program
to the @xlisp system.  With one exception,
declarations are completely optional
and correct declarations do not affect the meaning
of a correct program.  The exception is that
@f[special] declarations @i[do] affect the interpretation of variable
bindings and references, and so @i[must] be specified where appropriate.
All other declarations are of an advisory nature, and may be used
by the @xlisp system to aid the programmer by performing extra error checking
or producing more efficient compiled code.  Declarations are also
a good way to add documentation to a program.

Note that it is considered an error for a program to violate a
declaration (such as a @f[type] declaration), but an implementation is
not required to detect such errors (though such detection, where
feasible, is to be encouraged).

@Section[Declaration Syntax]

The @f[declare] construct is used for embedding declarations within
executable code.  Global declarations and declarations that are computed
by a program are established by the @f[proclaim] construct.

@Defspec[Fun {declare⎇, Args {@mstar<@i[decl-spec]>⎇]
A @f[declare] form is known as a @i[declaration].
Declarations may occur only at the beginning of the bodies of
certain special forms;
that is, a declaration may occur only as a statement
of such a special form, and all statements preceding it (if any) must
also be @f[declare] forms (or possibly documentation strings, in some cases).
Declarations may occur in lambda-expressions and in the following forms:
@lisp
@tabdivide[2]
@f[defmacro]@\@f[dotimes]
@f[defsetf]@\@f[flet]
@f[deftype]@\@f[labels]
@f[defun]@\@f[let]
@f[do*]@\@f[let*]
@f[do-all-symbols]@\@f[locally]
@f[do-external-symbols]@\@f[macrolet]
@f[do-symbols]@\@f[multiple-value-bind]
@f[do]@\@f[prog]
@f[dolist]@\@f[prog*]
@endlisp
It is an error to attempt to evaluate a declaration.
Those special forms that permit declarations to appear
perform explicit checks for their presence.
@Incompatibility{In @maclisp, @f[declare] is a special form
that does nothing but return the symbol @f[declare] as its
result.  The @maclisp interpreter knows nothing about declarations
but just blindly evaluates them, effectively ignoring them.
The @maclisp compiler recognizes declarations but processes
them simply by evaluating the subforms of the declaration in
the compilation context.  In @clisp it is
important that both the interpreter and compiler recognize
declarations (especially @f[special] declarations) and treat them
consistently,
and so the rules about the structure and use of declarations
have been made considerably more stringent.
The odd tricks played in @maclisp by writing arbitrary forms
to be evaluated within a @f[declare] form
are better done in both @maclisp and @clisp by using @Specref[eval-when].⎇

It is permissible for a macro call to expand into a declaration
and be recognized as such, provided that the macro call
appears where a declaration may legitimately appear.
(However, a macro call may not appear in place of a @i[decl-spec].)

Each @i[decl-spec] is a list whose @i[car] is a symbol
specifying the kind of declaration to be made.  Declarations may be
divided into two classes: those that concern the bindings of variables,
and those that do not.  (The @f[special] declaration is the sole
exception: it effectively falls into both classes, as explained below.)
Those that concern variable bindings apply
only to the bindings made by the form at the head of whose body they
appear.  For example, in
@Lisp
(defun foo (x)
  (declare (type float x)) ...
  (let ((x 'a)) ...)
  ...)
@Endlisp
the @f[type] declaration applies only to the outer binding of @f[x],
and not to the binding made in the @f[let].
@Incompatibility{This is different from @maclisp, in which type
declarations are pervasive.⎇

Declarations that do not concern themselves with variable bindings are
pervasive, affecting all code in the body of the special form.
As an example of a pervasive declaration,
@Lisp
(defun foo (x y) (declare (notinline floor)) ...)
@Endlisp
advises that everywhere within the body of @f[foo] the function
@f[floor] should not be open-coded but called as an out-of-line subroutine.

Some special forms contain pieces of code that, properly speaking,
are not part of the body of the special form.  Examples of this
are initialization forms that provide values for bound variables,
and the result forms of iteration constructs.
In all cases such additional code is within the scope of any pervasive
declarations appearing before the body of the special form.
Non-pervasive declarations have no effect on such code, except (of course)
in those situations where the code is defined to be within the scope
of the variables affected by such non-pervasive declarations.
For example:
@lisp
(defun few (x @optional (y @var[print-circle]))
  (declare (special @var[print-circle]))
  ...)
@endlisp
The reference to @Var[print-circle] in the first line of this example is special
because of the declaration in the second line.
@Lisp
(defun nonsense (k x z)
  (foo z x)			;First call to foo
  (let ((j (foo k x))		;Second call to foo
	(x (* k k)))
    (declare (inline foo) (special x z))
    (foo x j z)))		;Third call to foo
@Endlisp
In this rather nonsensical example,
the @F[inline] declaration applies to the
second and third calls to @f[foo], but not to the first one.
The @F[special] declaration of @f[x] causes the @f[let] form
to make a special binding for @f[x], and causes the reference to @f[x]
in the body of the @f[let] to be a special reference.
The reference to @f[x] in the second call to @f[foo] is also a special
reference.
The reference to @f[x] in the first call to @f[foo] is a local
reference, not a special one.  The @f[special] declaration of @f[z]
causes the reference to @f[z] in the call
to @f[foo] to be a special reference; it will not
refer to the parameter to @f[nonsense] named @f[z], because that
parameter binding has not been declared to be @f[special].
(The @f[special] declaration of @f[z] does not appear in the body
of the @f[defun], but in an inner construct, and therefore does not
affect the binding of the parameter.)
@Enddefspec

@Defmac[Fun {locally⎇, Args {@mstar<@i[declaration]> @mstar<@i[form]>⎇]
This special form may be used to make local pervasive declarations
where desired.   It does not bind any variables and therefore cannot
be used meaningfully for declarations of variable bindings.
(Note that the @f[special] declaration may be used with @f[locally]
to pervasively affect references to, rather than bindings of, variables.)
Foe example:
@Lisp
(locally (declare (inline floor) (notinline car cdr))
	 (declare (optimize space))
  (floor (car x) (cdr y)))
@Endlisp
@Enddefmac

@Defun[Fun {proclaim⎇, Args {@i[decl-spec]⎇]
The function @f[proclaim] takes a @i[decl-spec] as its
argument and puts it into effect globally.  (Such a global
declaration is called a @Def[proclamation].)
Because @f[proclaim] is a function, its argument is always evaluated.
This allows a program to compute a declaration and then put
it into effect by calling @f[proclaim].

Any variable names
mentioned are assumed to refer to the dynamic values of the
variable.  For example, the proclamation
@Lisp
(proclaim '(type float tolerance))
@Endlisp
once executed,
specifies that the dynamic value of @f[tolerance] should always
be a floating-point number.
Similarly, any function names mentioned are assumed to refer to
the global function definition.

A proclamation constitutes a universal declaration, always in force
unless locally shadowed.  For example,
@Lisp
(proclaim '(inline floor))
@Endlisp
advises that @f[floor] should normally be open-coded in-line by the
compiler (but in the situation
@Lisp
(defun foo (x y) (declare (notinline floor)) ...)
@Endlisp
it will be compiled out-of-line anyway in the body of @f[foo],
because of the shadowing local declaration to that effect).

As a special case (so to speak), @f[proclaim] treats a @f[special]
@i[declaration-form] as applying to all bindings as well as to
all references of the mentioned variables.  For example, after
@lisp
(proclaim '(special x))
@endlisp
then in a function definition such as
@lisp
(defun example (x) ...)
@endlisp
the parameter @f[x] will be bound as a special (dynamic) variable
rather than as a lexical (static) variable.  This facility should
be used with caution.  The usual way to define a globally special
variable is with @Macref[defvar] or @Macref[defparameter].
@Enddefun

@Section[Declaration Specifiers]

Here is a list of valid declaration specifiers for use in
@f[declare].  A construct is said to be ``affected'' by a declaration
if it occurs within the scope of a declaration.

@Begin[Description]
@Begin[Multiple]
@f[special]@\@}
@f[(special @i[var1] @i[var2] ...)] specifies that all of
the variables named are to be considered @i[special].
This specifier affects variable bindings but also pervasively
affects references.
All variable bindings affected are made to be dynamic bindings,
and affected variable references refer to the current dynamic binding
rather than the current local binding.
For example:
@lisp
(defun hack (thing *mod*)    ;@r[The binding of the parameter]
  (declare (special *mod*))  ; @r[@f[*mod*] is visible to @f[hack1],]
  (hack1 (car thing)))	     ; @r[but not that of @f[thing].]

(defun hack1 (arg)
  (declare (special *mod*))  ;@r[Declare references to @f[*mod*]]
			     ; @r[within @f[hack1] to be special.]
  (if (atom arg) *mod*
      (cons (hack1 (car arg)) (hack1 (cdr arg)))))
@endlisp
Note that it is conventional, though not required, to give special
variables names that begin and end with an asterisk.	

A @f[special] declaration does @i[not] affect bindings pervasively.
Inner bindings of a variable implicitly shadow
a @f[special] declaration and must be explicitly re-declared to
be special.
(However, a @f[special] proclamation @i[does] pervasively affect bindings;
this exception is made for reasons of
convenience and compatibility with @maclisp.)
For example:
@lisp
(proclaim '(special x))		;@r[@f[x] is always special.]

(defun example (x y)
  (declare (special y))
  (let ((y 3) (x (* x 2)))
    (print (+ y (locally (declare (special y)) y)))
    (let ((y 4)) (declare (special y)) (foo x))))
@Endlisp
In the contorted code above, the outermost and innermost bindings of
@f[y] are special and therefore dynamically scoped, but the middle
binding is lexically scoped.  The two arguments to @f[+] are different,
one being the value, which is @f[3], of the lexically bound variable
@f[y], and the other being the value of the special variable named @f[y]
(a binding of which happens, coincidentally, to lexically surround it at
an outer level).  All the bindings of @f[x] and references to @f[x]
are special, however, because of the proclamation that @f[x] is
always @f[special].

As a matter of style, use of @f[special] proclamations should be
avoided.  The @Macref[defvar] and @f[defparameter] macros
are the conventional means for proclaiming special variables
in a program.
@End[Multiple]

@f[type]@\@}
@f[(type @i[type] @i[var1] @i[var2] ...)] affects
only variable bindings and specifies that the
variables mentioned will take on values only of the specified type.
In particular, values assigned to the variables by @Specref[setq],
as well as the initial values of the variables, must be of
the specified type.

@Begin[Multiple]
@i[type]@\@}
@f[(@i[type] @i[var1] @i[var2] ...)]
is an abbreviation for
@f[(type @i[type] @i[var1] @i[var2] ...)],
provided that @i[type] is one of the symbols appearing
in Table @Ref[TYPE-SYMBOLS-TABLE].
@End[Multiple]

@Begin[Multiple]
@f[ftype]@\@}
@f[(ftype @i[type] @i[function-name-1] @i[function-name-2] ...)]
specifies that the named functions will be of the functional type
@i[type].
For example:
@lisp
(declare (ftype (function (integer list) t) nth)
	 (ftype (function (number) float) sin cos))
@Endlisp
Note that rules of lexical scoping are observed; if one of the functions
mentioned has a lexically apparent local definition
(as made by @Specref[flet] or @Specref[labels]), then the declaration
applies to that local definition and not to the global function definition.
@End[Multiple]

@Begin[Multiple]
@f[function]@\@}
@f[(function @i[name] @i[arglist] @i[result-type1] @i[result-type2] ...)]
is entirely equivalent to
@Lisp
@f[(ftype (function @i[arglist] @i[result-type1] @i[result-type2] ...) @i[name])]
@Endlisp
but may be more convenient for some purposes.
For example:
@lisp
(declare (function nth (integer list) t)
	 (function sin (number) float)
	 (function cos (number) float))
@Endlisp
The syntax mildly resembles that of @Macref[defun]: a function name,
then an argument list, then a specification of results.

Note that rules of lexical scoping are observed; if one of the functions
mentioned has a lexically apparent local definition
(as made by @Specref[flet] or @Specref[labels]), then the declaration
applies to that local definition and not to the global function definition.
@End[Multiple]

@Begin[Multiple]
@f[inline]@\@}
@f[(inline @i[function1] @i[function2] ...)] specifies that
it is desirable for the compiler to open-code
calls to the specified functions; that is, the code for a specified function
should be integrated into the calling routine, appearing ``in line''
in place of a procedure call.  This may achieve
extra speed at the expense of debuggability (calls to functions
compiled in-line cannot be traced, for example).
This declaration is pervasive.
Remember that
a compiler is free to ignore this declaration.

Note that rules of lexical scoping are observed; if one of the functions
mentioned has a lexically apparent local definition
(as made by @Specref[flet] or @Specref[labels]), then the declaration
applies to that local definition and not to the global function definition.
@End[Multiple]

@Begin[Multiple]
@f[notinline]@\@}
@f[(notinline @i[function1] @i[function2] ...)] specifies that it is
@i[undesirable] to compile the specified functions in-line.
This declaration is pervasive.
A compiler is @i[not] free to ignore this declaration.

Note that rules of lexical scoping are observed; if one of the functions
mentioned has a lexically apparent local definition
(as made by @Specref[flet] or @Specref[labels]), then the declaration
applies to that local definition and not to the global function definition.
@End[Multiple]

@Begin[Multiple]
@f[ignore]@\@}
@f[(ignore @i[var1] @i[var2] ... @i[varn])] affects only variable bindings
and specifies that the bindings
of the specified variables are never used.  It is desirable for a compiler
to issue a warning if a variable so declared is ever referred to
or is also declared special, or if a variable is lexical, never referred to,
and not declared to be ignored.
@End[Multiple]

@Begin[Multiple]
@f[optimize]@\@}
@f[(optimize (@i[quality1] @i[value1]) (@i[quality2] @i[value2])...)]
advises the compiler that each @i[quality] should be given attention
according to the specified corresponding @i[value].
A quality is a symbol; standard qualities
include @f[speed] (of the object code), @f[space] (both code size and
run-time space), @f[safety] (run-time error checking),
and @f[compilation-speed] (speed of the compilation process).
Other qualities may be recognized by particular implementations.
A @i[value] should be a non-negative integer, normally in the range
@f[0] to @f[3].  The value @f[0] means that the quality is totally
unimportant, and @f[3] that the quality is extremely important;
@f[1] and @f[2] are intermediate values, with @f[1] the ``normal''
or ``usual'' value.
One may abbreviate @f[(@i[quality] 3)] to simply @i[quality].
This declaration is pervasive.
For example:
@lisp
(defun often-used-subroutine (x y)
  (declare (optimize (safety 2)))
  (error-check x y)
  (hairy-setup x)
  (do ((i 0 (+ i 1))
       (z x (cdr z)))
      ((null z))
    ;; This inner loop really needs to burn.
    (declare (optimize speed))
    (declare (fixnum i))
    )))
@Endlisp
@End[Multiple]

@Begin[Multiple]
@f[declaration]@\@}
@f[(declaration @i[name1] @i[name2] ...)] advises the compiler
that each @i[namej] is a valid but non-standard declaration name.
The purpose of this is to tell one compiler not to issue warnings
for declarations meant for another compiler or other program processor.
This kind of declaration may be used only as a proclamation.
For example:
@lisp
(proclaim '(declaration author
			target-language
	                target-machine))

(proclaim '(target-language ada))

(proclaim '(target-machine IBM-650))

(defun strangep (x)
  (declare (author "Harry Tweeker"))
  (member x '(strange weird odd peculiar)))
@endlisp
@End[Multiple]
@End[Description]
An implementation is free to support other (implementation-dependent)
declaration specifiers as well.
On the other hand, a @clisp compiler is free to
ignore entire classes of declaration specifiers (for example,
implementation-dependent declaration specifiers
not supported by that compiler's
implementation!), except for the @f[declaration] declaration specifier.
Compiler implementors are encouraged, however, to
program the compiler to issue by default a warning if the compiler finds
a declaration specifier of a kind it never uses.  Such a warning is required
in any case
if a declaration specifier is not one of those defined above and has not been
declared in a @f[declaration] declaration.

@Section[Type Declaration for Forms]

Frequently it is useful to declare that the value produced
by the evaluation of some form will be of a particular type.
Using @f[declare] one can declare the type of the value
held by a bound variable, but there is no easy way to declare
the type of the value of an unnamed form.  For this purpose the @f[the]
special form is defined; @f[(the @i[type] @i[form])] means
that the value of @i[form] is declared to be of type @i[type].

@Defspec[Fun {the⎇, Args {@i[value-type] @i[form]⎇]
The @i[form] is evaluated; whatever it produces is returned by
the @f[the] form.  In addition, it is an error if what is produced
by the @i[form] does not conform to the data type specified by @i[value-type]
(which is not evaluated).  (A given implementation may or may not
actually check for this error.  Implementations are encouraged to make an
explicit error check when running interpretively.)  In effect, this
declares that the user undertakes to guarantee that the values of
the form will always be of the specified type.
For example:
@lisp
(the string (copy-seq x))	 ;@r[The result will be a string.]
(the integer (+ x 3))		 ;@r[The result of @f[+] will be an integer.]
(+ (the integer x) 3)		 ;@r[The value of @f[x] will be an integer.]
(the (complex rational) (* z 3))
(the (unsigned-byte 8) (logand x mask))
@Endlisp
The @f[values] type specifier may be used to indicate the types
of multiple values:
@lisp
(the (values integer integer) (floor x y))
(the (values string t)
     (gethash the-key the-string-table))
@endlisp

@Incompatibility{This construct is borrowed from the @interlisp @c[DECL]
package; @interlisp, however, allows an implicit @f[progn] after the type
specifier rather than just a single form.  The @maclisp @f[fixnum-identity]
and @f[flonum-identity] constructs can be expressed as @f[(the fixnum @i[x])]
and @f[(the single-float @i[x])].⎇
@Enddefspec